package com.starsoft.trade.trader;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.Header;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.starsoft.frame.util.DateUtil;
import com.starsoft.frame.util.EnvUtil;
import com.starsoft.frame.util.StringUtil;
import com.starsoft.smdc.bean.SmdcSecurity;
import com.starsoft.trade.bean.TradeAcount;
import com.starsoft.trade.bean.TradeAcountStatus;
import com.starsoft.trade.bean.TradeBill;
import com.starsoft.trade.bean.TradePosition;
import com.starsoft.trade.bean.TradePositionId;
import com.starsoft.trade.bean.TradeSummary;
import com.starsoft.trade.bean.TradeSummaryId;
import com.starsoft.trade.order.Order;
import com.starsoft.trade.trader.bean.YjbResponse;
import com.starsoft.trade.util.TradeType;

public class YjbTrader extends AbstractTrader {

	private static Logger logger = LoggerFactory.getLogger(YjbTrader.class);
	
	String loginPage="https://jy.yongjinbao.com.cn/winner_gj/gjzq/";
	String yjbApi = "https://jy.yongjinbao.com.cn/winner_gj/gjzq/exchange.action";
	String verifyCodeUrl = "https://jy.yongjinbao.com.cn/winner_gj/gjzq/user/extraCode.jsp";

	String username;
	String password;
	String portflioName;
	double multiply;

	public void init(TradeAcount acount, Map<String, String> apiMap, TraderContextService service) {
		super.init(acount, apiMap, service);
		if(config.containsKey("username")){
			username = config.get("username");
		} else {
			throw new RuntimeException("未配置username");
		}
		if(config.containsKey("password")){
			try {
				password = URLDecoder.decode(config.get("password"),"utf-8");
			} catch (UnsupportedEncodingException e) {
				throw new RuntimeException("配置password错误");
			}
		} else {
			throw new RuntimeException("未配置password");
		}
	}

	public void login() {
		httpGet(loginPage, null);
		
		// 设置登陆时要求的信息，用户名和密码
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		params.add(new BasicNameValuePair("account_content", username));
		params.add(new BasicNameValuePair("password", password));
		params.add(new BasicNameValuePair("mac_addr", EnvUtil.getMac()));
		
		params.add(new BasicNameValuePair("function_id", "200"));
		params.add(new BasicNameValuePair("login_type", "stock"));
		params.add(new BasicNameValuePair("version", "200"));
		params.add(new BasicNameValuePair("input_content", "1"));
		params.add(new BasicNameValuePair("cpuid", "-20655-9AE3BD"));
		params.add(new BasicNameValuePair("loginPasswordType", "B64"));
		params.add(new BasicNameValuePair("disk_serial_id", "100825PBN40317ERH81E"));
		params.add(new BasicNameValuePair("machinecode", "-20655-9AE3BD"));
		
		String responseStr = httpPost(yjbApi, defaultHeaders(), params);
		logger.info(responseStr);
		YjbResponse response=new YjbResponse(responseStr);
		if(response.getMsgNo()!=0){
			throw new RuntimeException("登录失败,"+response.getMsgInfo());
		}
	}

	public TradeAcountStatus getPortflio() {
		Date asofDate = contextService.getPotflioDate();
		
		String positionUrl = yjbApi+"?service_type=stock&request_id=mystock_403&sort_direction=0&timestamp="+Math.random();
		String posResStr = httpGet(positionUrl, defaultHeaders());
		YjbResponse posRes=new YjbResponse(posResStr);
		List<TradePosition> positions = new ArrayList<>();
		for (int i = 0; i < posRes.getData().size(); i++){
			Map<String, String> holding = posRes.getData(i);
			String secId = convertSecId(holding.get("stock_code"), true);
			double secNum = Double.parseDouble(holding.get("current_amount"));
			double secNumAfs = Double.parseDouble(holding.get("enable_amount"));
			TradePosition position = new TradePosition();
			position.setId(new TradePositionId(null, asofDate, secId));
			position.setSecNum(secNum);
			position.setSecNumAfs(secNumAfs);
			positions.add(position);
		}
		
		String summaryUrl = yjbApi+"?request_id=mystock_405&timestamp="+Math.random();
		String summaryResStr = httpGet(summaryUrl, defaultHeaders());
		YjbResponse summaryRes=new YjbResponse(summaryResStr);
		Map<String, String> summaryMap = summaryRes.getData(0);
		TradeSummary summary = new TradeSummary();
		summary.setId(new TradeSummaryId(null, asofDate));
		summary.setNetAssert(Double.parseDouble(summaryMap.get("asset_balance")));
		summary.setMarketValue(Double.parseDouble(summaryMap.get("market_value")));	
		summary.setCash(summary.getNetAssert()-summary.getMarketValue());
		TradeAcountStatus status = new TradeAcountStatus(null, summary, positions);
		return contextService.fillStatus(acount, status);
	}

	public List<TradeBill> getHistory(Date beginDate) {
		List<TradeBill> bills = new ArrayList<TradeBill>();
//		String todayBargainUrl = yjbApi + "?service_type=stock&request_id=bargain_402&sort_direction=1&timestamp="
//				+ Math.random();
//		YjbResponse todayBarRes = new YjbResponse(httpGet(todayBargainUrl, defaultHeaders()));
//		bills = getBillsFromBargin(todayBarRes);

		String beginDateStr = DateUtil.toString(beginDate, "yyyyMMdd");
		String endDateStr = DateUtil.toString(new Date(), "yyyyMMdd");
		String oldBargainUrl = yjbApi + "?service_type=stock&request_id=bargain_411&sort_direction=1&request_num=1000";
		oldBargainUrl += "&begin_date=" + beginDateStr + "&start_date=" + beginDateStr + "&end_date=" + endDateStr
				+ "&timestamp=" + Math.random();
		YjbResponse oldBarRes = new YjbResponse(httpGet(oldBargainUrl, defaultHeaders()));
		bills.addAll(getBillsFromBargin(oldBarRes));
		
		String liuShuiUrl = yjbApi + "?service_type=stock&function_id=412&sort_direction=0&request_num=1000";
		liuShuiUrl += "&begin_date=" + beginDateStr + "&start_date=" + beginDateStr + "&end_date=" + endDateStr
				+ "&timestamp=" + Math.random();
		YjbResponse liuShuiRes = new YjbResponse(httpGet(liuShuiUrl, defaultHeaders()));
		bills.addAll(getBillsFromLiuShui(liuShuiRes));
		
		return contextService.fillBills(acount, bills);
	}
	
	private List<TradeBill> getBillsFromBargin(YjbResponse response){
		List<TradeBill> bills = new ArrayList<TradeBill>();
		for(Map<String, String> data : response.getData()){
			String date = data.get("date");
			if(StringUtil.isEmpty(date)){
				 date = data.get("init_date");
			}
			String acount = data.get("occur_amount");
			if(StringUtil.isEmpty(acount)){
				acount = data.get("business_amount");
			}
			String timeStr = date +" "+data.get("business_time").replace(" ", "");
			Timestamp billTime = DateUtil.toStamp(DateUtil.toDate(timeStr, "yyyy-MM-dd hh:mm:ss"));
			String secId = null;
			try {
				secId = convertSecId(data.get("stock_code"), true);
			} catch (Exception e) {
				logger.warn("not support security code:"+ data.get("stock_code"));
				continue;
			}
			TradeBill bill = new TradeBill();
			bill.setExId(data.get("serial_no"));
			bill.setBillDesc("同步佣金宝," + DateUtil.toString(new Date()));
			bill.setSecId(secId);
			bill.setSecNum(Double.parseDouble(acount));
			bill.setSecPrice(Double.parseDouble(data.get("business_price")));
			bill.setBillTime(billTime);
			bills.add(bill);
		}
		return bills;
	}

	private List<TradeBill> getBillsFromLiuShui(YjbResponse response){
		List<TradeBill> bills = new ArrayList<TradeBill>();
		for(Map<String, String> data : response.getData()){
			TradeType tradeType = null;
			String busiName = data.get("business_name");
			if("银行转存".equals(busiName)|| "银行转取".equals(busiName)){
				tradeType = TradeType.transfer;
			} else {
				continue;
			}
			String timeStr = data.get("business_date") +" 09:20:00";
			Timestamp billTime = DateUtil.toStamp(DateUtil.toDate(timeStr, "yyyy-MM-dd hh:mm:ss"));
	
			TradeBill bill = new TradeBill();
			bill.setBillType(tradeType.name());
			bill.setBillDesc("同步佣金宝," + DateUtil.toString(new Date()));
			bill.setBillTradeMoney(Double.parseDouble(data.get("occur_balance")));
			bill.setBillTime(billTime);
			bills.add(bill);
		}
		return bills;
	}
	
	private Header[] defaultHeaders() {
		Header[] headers = new Header[1];
		headers[0] = new BasicHeader("User-Agent",
				"Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko");
		return headers;
	}

	@Override
	public void trade(List<Order> orders) {

	}

	private String convertSecId(String code, boolean toLocal) {
		String ticker = this.convertTicker(code);
		if (toLocal) {
			SmdcSecurity security = contextService.getSecurityByTicker(ticker);
			return security.getSecId();
		} else {
			return ticker;
		}
	}

	private String convertTicker(String code) {
		Pattern pa = Pattern.compile("(\\d+)");
		Matcher ma = pa.matcher(code);
		if (ma.find()) {
			return ma.group();
		} else {
			return code;
		}
	}

	@Override
	public List<TradeBill> getEntrust() {
		List<TradeBill> bills = new ArrayList<TradeBill>();

		return bills;
	}

	@Override
	public void cancelEntrust(List<TradeBill> bills) {
		if (bills == null || bills.isEmpty()) {
			return;
		}
	}
	
	@Override
	public List<TradeBill> getHistory(InputStream startDate) {
		throw new RuntimeException("not support");
	}

}
